package com.example.demo.nios.selector2;


import org.hibernate.boot.spi.InFlightMetadataCollector;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;

public class Server {
    public static void main(String[] args) {
        try {


            Integer port = 50000;
            Boolean flag = true;
            String message = null;
            //字符集
            Charset charset = Charset.forName("UTF-8");
            //字节缓冲器
            ByteBuffer byteBuffer = ByteBuffer.allocate(10);
            //打开选择器
            Selector selector = Selector.open();
            //创建服务端频道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            ServerSocket serverSocket = serverSocketChannel.socket();
            serverSocket.bind(new InetSocketAddress(port));
            //设置非阻塞模式
            serverSocketChannel.configureBlocking(false);
            //将频道注册到选择器
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            while (flag) {
                //当注册的事件到达时，方法返回；否则,该方法会一直阻塞
                selector.select();
                //通道令牌
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    //必须要删除，避免通道冲突
                    iterator.remove();
                    //可接收连接
                    if (selectionKey.isAcceptable()) {
                        ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel) selectionKey.channel();
                        //与客户端建立了连接
                        SocketChannel socketChannel = serverSocketChannel1.accept();
                        socketChannel.configureBlocking(false);
                        //将连接加入到选择器 ,等待消息的接收与发送
                        socketChannel.register(selector, SelectionKey.OP_READ );
                        System.out.println("一个客户端上线，占用端口：" + socketChannel.socket().getPort());
                    }

                    //可读取
                    else if (selectionKey.isReadable()) {
                            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                            StringBuffer stringBuffer = new StringBuffer();

                            //将消息读取到字节缓冲器
                           Integer res = 0;
                           try{
                               res = socketChannel.read(byteBuffer);
                           }
                           catch (Exception e){
                               e.printStackTrace();
                           }
                           if(res <=0 ){
                               selectionKey.cancel();
                               System.out.println(String.format("通道关闭：%s",socketChannel.socket().getPort()));
                           }
                           else{
                               byteBuffer.flip();
                               stringBuffer.append(charset.decode(byteBuffer));
                               //读取完后清除缓冲器
                               byteBuffer.clear();
                               message = stringBuffer.toString();
                               System.out.println(String.format("通道:%s,消息:%s", socketChannel.socket().getPort(), stringBuffer.toString()));
                           }


                        }

                    //可发送
                    else if (selectionKey.isWritable()) {
//                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
//                    socketChannel.write(charset.encode("老子接收到你的消息:"+message));
                    }



                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
